{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Robustness Evaluation with Security Curves\n",
    "\n",
    "This notebook demonstrates how to use the ART evaluations module for generating Security Curves. Security Curves have been widely used in the literature to determine and compare the robustness of machine learning models against adversarial examples [1, 2], as well as to identify shortcomings of defences - gradient masking in particular - which could be exploited by an adaptive adversary [3]. Essentially, Security Curves convey the performance of a given model under increasing attack perturbation budgets - commonly in terms of an l_p norm.\n",
    "\n",
    "[1] A. Madry et al.: Towards Machine Learning Models Resistant to Adversarial Attacks. https://arxiv.org/abs/1706.06083\n",
    "<br>\n",
    "[2] Y. Dong et al.: Benchmarking Adversarial Robustness on Image Classification. https://arxiv.org/abs/1912.11852\n",
    "<br>\n",
    "[3] N. Carlini et al.: On Evaluating Adversarial Robustness. https://arxiv.org/abs/1902.06705"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from keras.models import load_model\n",
    "\n",
    "from robustness.datasets import CIFAR\n",
    "from robustness.model_utils import make_and_restore_model\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "from art.config import ART_DATA_PATH\n",
    "from art.utils import load_dataset, get_file\n",
    "from art.evaluations.security_curve import SecurityCurve\n",
    "\n",
    "from art.estimators.classification import PyTorchClassifier, KerasClassifier"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Evaluate robust classifier trained with adversarial training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load CIFAR-10 dataset\n",
    "(x_train_cifar, y_train_cifar), (x_test_cifar, y_test_cifar), min_cifar, max_cifar = load_dataset(\"cifar10\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Change format frm NHWC to NCHW for PyTorch\n",
    "x_train_cifar = np.transpose(x_train_cifar, (0, 3, 1, 2)).astype(np.float32)\n",
    "x_test_cifar = np.transpose(x_test_cifar, (0, 3, 1, 2)).astype(np.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define argument for PGD attack used in evaluation, except `classifier` and `eps`\n",
    "kwargs_pgd = {\"norm\": \"inf\",\n",
    "              \"eps_step\": 1/255,\n",
    "              \"max_iter\": 100,\n",
    "              \"targeted\": False,\n",
    "              \"num_random_init\": 0,\n",
    "              \"batch_size\": 128,\n",
    "              \"random_eps\": False,\n",
    "              \"verbose\": False,\n",
    "             }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define attack budgets for evaluation as a list of floats\n",
    "eps = [i / 255 for i in range(1, 32, 2)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an instance of a Security Curve evaluation\n",
    "sc = SecurityCurve(eps=eps)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=> loading checkpoint '/tmp/cifar_linf_8.pt'\n",
      "=> loaded checkpoint '/tmp/cifar_linf_8.pt' (epoch 153)\n"
     ]
    }
   ],
   "source": [
    "# Load a robust PyTorch model using the package `robustness` (https://github.com/MadryLab/robustness)\n",
    "path_to_cifar10_data = \"/tmp/data/\"\n",
    "resume_path = \"/tmp/cifar_linf_8.pt\"\n",
    "\n",
    "ds = CIFAR(path_to_cifar10_data)\n",
    "m, _ = make_and_restore_model(arch='resnet50',\n",
    "                              dataset=ds,\n",
    "                              resume_path=resume_path,\n",
    "                             )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define mean and standard-deviation for preprocessing of the PyTorch model\n",
    "mean=np.asarray([0.4914, 0.4822, 0.4465]).reshape(3, 1, 1).astype(np.float32)\n",
    "std=np.asarray([0.2023,  0.1994, 0.2010]).reshape(3, 1, 1).astype(np.float32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an ART estimator for the PyTorch classification model\n",
    "robust_classifier_cifar = PyTorchClassifier(model=m.model, \n",
    "                                            clip_values=(min_cifar, max_cifar),\n",
    "                                            loss=torch.nn.CrossEntropyLoss(),\n",
    "                                            input_shape=(3, 32, 32),\n",
    "                                            nb_classes=10,\n",
    "                                            preprocessing=(mean, std))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Evaluate Security Curve for robust PyTorch classifier on CIFAR-10 on the first 100 samples\n",
    "eps_list, accuracy_adv_list, accuracy = sc.evaluate(classifier=robust_classifier_cifar,\n",
    "                                                    x=x_train_cifar[0:100],\n",
    "                                                    y=y_train_cifar[0:100],\n",
    "                                                    **kwargs_pgd)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the Security Curve for the evaluation of the robust PyTorch classifier on CIFAR-10\n",
    "sc.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Check if the robust PyTorch classifier is potentially obfuscating loss gradients\n",
    "sc.detected_obfuscating_gradients"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Robust Classifier with Gradient Obfuscation by Vanishing Gradients"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load MNIST dataset\n",
    "(x_train_mnist, y_train_mnist), (x_test_mnist, y_test_mnist), min_mnist, max_mnist = load_dataset('mnist')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load a robust Keras model with potential gradient obfuscation caused by vanishing gradients.\n",
    "path = get_file('mnist_cnn_robust.h5', extract=False, path=ART_DATA_PATH,\n",
    "                url='https://www.dropbox.com/s/yutsncaniiy5uy8/mnist_cnn_robust.h5?dl=1')\n",
    "robust_classifier_model = load_model(path)\n",
    "robust_classifier_mnist = KerasClassifier(clip_values=(min_mnist, max_mnist),\n",
    "                                          model=robust_classifier_model,\n",
    "                                          use_logits=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define argument for PGD attack used in evaluation, except `classifier` and `eps`\n",
    "kwargs_pgd = {\"norm\": \"inf\",\n",
    "              \"eps_step\": 1/255,\n",
    "              \"max_iter\": 100,\n",
    "              \"targeted\": False,\n",
    "              \"num_random_init\": 0,\n",
    "              \"batch_size\": 128,\n",
    "              \"random_eps\": False,\n",
    "              \"verbose\": False,\n",
    "             }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define attack budgets for evaluation as number of evaluations equally spaced between minimal and \n",
    "# maximal `eps`.\n",
    "eps = 64"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an instance of a Security Curve evaluation\n",
    "sc = SecurityCurve(eps=eps)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Evaluate Security Curve for robust PyTorch classifier on CIFAR-10 on the first 100 samples\n",
    "eps_list, accuracy_adv_list, accuracy = sc.evaluate(classifier=robust_classifier_mnist,\n",
    "                                                    x=x_train_mnist[0:100],\n",
    "                                                    y=y_train_mnist[0:100],\n",
    "                                                    **kwargs_pgd)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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p7Kykk6dOtGvXz/ShGJFEBEsXryYyspK+vfv39ThmFkjaRF3Fq9atYru3bs7CRSZJLp37+4zL7MWpkUkAsBJoES8n81anhaTCMzMbNNkMhFMmLmIYZc9Tv+xDzLssseZMHNRSbZ74403ctppp5VkWxty8MEHs3Tp0gaX6devH++//36JIjKzplLUxuIt0YSZizjv3n+ycs06ABYtXcl59/4TgMN2b+jG5y3H2rVrad160966iCAimDhx4oYXNrNMaHGJ4KK/zuKVt/5d7/yZC5ayet0nNaatXLOOc+5+idufXZD3NYO26cwFh+60wW0fdthhLFy4kFWrVnHmmWcyZswYbrjhBi699FJ69erF9ttvT9u2bVm2bBm77bYb8+bNo1WrVqxYsYKBAwcyb948FixYwKmnnkpVVRUdOnTguuuuY4cdduD4449n6623ZubMmeyxxx6MGjWKM888E0jq7Z988kkkMXr0aJYsWcKaNWu45JJLGD16NPPnz2fkyJGMGDGCqVOnMmHCBPbdd1+mT59Ojx498sZtZtnR4hLBhtROAhuavjGuv/56tt56a1auXMlee+3FIYccwgUXXMCMGTPo0qULI0aMYPfdd6dLly7stttuPPHEE4wYMYK//vWvHHjggZSXlzNmzBjGjRvHgAEDeOaZZzjllFN4/PHHAXjttdd47LHHKCsr49BDD+Xqq69m2LBhLF++nHbt2gFw33330blzZ95//32GDh3KqFHJbRlz5szhhhtu4Jprrtlg3EcccQTdu3ff7P1hZs1Di0sEG/rlPuyyx1m0dGWd6b27tufO731xs7Z91VVXcd999wGwcOFCbrnlFoYPH051/0hHHXUUr7322vrhO++8kxEjRnDHHXdwyimnsHz5cqZMmcKRRx65fp0ff/xprxtHHnkkZWVlSTmGDeOss87iW9/6Focffjh9+vRhzZo1/OQnP+HJJ5+kVatWLFq0iHfffReA7bbbjqFDhxYU9+uvv+5EYJYhLS4RbMjZBw6s0UYA0L68jLMPHLhZ6508eTKPPfYYU6dOpUOHDgwfPpwddtiB2bNn511+1KhRnHfeeXzwwQfMmDGD/fbbj48++oiuXbvywgsv5H3NVltttX547NixHHLIIUycOJGhQ4fy2GOPMW3aNKqqqpgxYwbl5eX069dv/TX/ua/dUNy+T8AsWzJ31dBh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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the Security Curve for the evaluation of the robust PyTorch classifier on CIFAR-10\n",
    "sc.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Check if the robust PyTorch classifier is potentially obfuscating loss gradients\n",
    "sc.detected_obfuscating_gradients"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.4.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
